home *** CD-ROM | disk | FTP | other *** search
- Path: xanth!cs.odu.edu!Amiga-Request
- From: Amiga-Request@cs.odu.edu (Amiga Sources/Binaries Moderator)
- Newsgroups: comp.sources.amiga
- Subject: v90i128: tar - tape archive utility, Part03/05
- Message-ID: <11981@xanth.cs.odu.edu>
- Date: 29 Mar 90 03:10:34 GMT
- Sender: tadguy@cs.odu.edu
- Reply-To: hue@netcom.uucp (Jonathan Hue)
- Lines: 1838
- Approved: tadguy@cs.odu.edu (Tad Guy)
- X-Mail-Submissions-To: Amiga@cs.odu.edu
- X-Post-Discussions-To: comp.sys.amiga
-
- Submitted-by: hue@netcom.uucp (Jonathan Hue)
- Posting-number: Volume 90, Issue 128
- Archive-name: unix/tar/part03
-
- #!/bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 3 (of 5)."
- # Contents: create.c extract.c port.c
- # Wrapped by tadguy@xanth on Wed Mar 28 22:07:16 1990
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'create.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'create.c'\"
- else
- echo shar: Extracting \"'create.c'\" \(15979 characters\)
- sed "s/^X//" >'create.c' <<'END_OF_FILE'
- X/*
- X * Create a tar archive.
- X *
- X * Written 25 Aug 1985 by John Gilmore, ihnp4!hoptoad!gnu.
- X *
- X * @(#)create.c 1.36 11/6/87 Public Domain - gnu
- X */
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X#include <stdio.h>
- X
- X#ifndef V7
- X#include <fcntl.h>
- X#endif
- X
- X#if !defined(MSDOS) && !defined(AMIGA)
- X#include <pwd.h>
- X#include <grp.h>
- X#endif
- X
- X#ifdef BSD42
- X#include <sys/dir.h>
- X#else
- X#ifdef MSDOS
- X#include <sys/dir.h>
- X#else
- X#ifdef AMIGA
- X#include <dirent.h>
- X#else
- X/*
- X * FIXME: On other systems there is no standard place for the header file
- X * for the portable directory access routines. Change the #include line
- X * below to bring it in from wherever it is.
- X */
- X#include "ndir.h"
- X#endif
- X#endif
- X#endif
- X
- X#ifdef USG
- X#include <sys/sysmacros.h> /* major() and minor() defined here */
- X#endif
- X
- X/*
- X * V7 doesn't have a #define for this.
- X */
- X#ifndef O_RDONLY
- X#define O_RDONLY 0
- X#endif
- X
- X/*
- X * Most people don't have a #define for this.
- X */
- X#ifndef O_BINARY
- X#define O_BINARY 0
- X#endif
- X
- X#include "tar.h"
- X#include "port.h"
- X
- Xextern union record *head; /* Points to current tape header */
- Xextern struct stat hstat; /* Stat struct corresponding */
- Xextern int head_standard; /* Tape header is in ANSI format */
- X
- X/*
- X * If there are no symbolic links, there is no lstat(). Use stat().
- X */
- X#ifndef S_IFLNK
- X#define lstat stat
- X#endif
- X
- Xextern char *malloc();
- Xextern char *strcpy();
- Xextern char *strncpy();
- Xextern void bzero();
- Xextern void bcopy();
- Xextern int errno;
- X
- Xextern void print_header();
- X
- Xunion record *start_header();
- Xvoid finish_header();
- Xvoid finduname();
- Xvoid findgname();
- Xchar *name_next();
- Xvoid to_oct(), to_hex();
- Xvoid dump_file();
- X
- Xstatic nolinks; /* Gets set if we run out of RAM */
- X
- Xvoid
- Xcreate_archive()
- X{
- X register char *p;
- X
- X open_archive(0); /* Open for writing */
- X
- X while (p = name_next()) {
- X#ifdef AMIGA
- X if (!strcmp(p, ".")) /* convert . and ./ to "" */
- X p++;
- X else if (!strcmp(p, "./"))
- X p += 2;
- X#endif
- X dump_file(p, -1);
- X }
- X
- X write_eot();
- X close_archive();
- X name_close();
- X}
- X
- X/*
- X * Dump a single file. If it's a directory, recurse.
- X * Result is 1 for success, 0 for failure.
- X * Sets global "hstat" to stat() output for this file.
- X */
- Xvoid
- Xdump_file(p, curdev)
- X char *p; /* File name to dump */
- X int curdev; /* Device our parent dir was on */
- X{
- X union record *header;
- X char type;
- X
- X /*
- X * Use stat if following (rather than dumping) 4.2BSD's
- X * symbolic links. Otherwise, use lstat (which, on non-4.2
- X * systems, is #define'd to stat anyway.
- X */
- X if (0 != f_follow_links? stat(p, &hstat): lstat(p, &hstat))
- X {
- Xbadperror:
- X perror(p);
- Xbadfile:
- X errors++;
- X return;
- X }
- X
- X /*
- X * See if we are crossing from one file system to another,
- X * and avoid doing so if the user only wants to dump one file system.
- X */
- X if (f_local_filesys && curdev >= 0 && curdev != hstat.st_dev) {
- X annorec(stderr, tar);
- X fprintf(stderr,
- X "%s: is on a different filesystem; not dumped\n",
- X p);
- X return;
- X }
- X#ifdef AMIGA
- X /*
- X * If f_archive_check is set, check the archived bit of the
- X * file and don't archive it if the bit is set and it's a normal
- X * file.
- X */
- X if (f_archive_check && (hstat.st_prot & FIBF_ARCHIVE) &&
- X !(hstat.st_mode & S_IFDIR))
- X {
- X if (f_verbose > 1)
- X {
- X annorec(stderr, tar);
- X fprintf(stderr, "%s: archive bit set, not dumping\n", p);
- X }
- X return;
- X }
- X#endif
- X
- X /*
- X * Check for multiple links.
- X *
- X * We maintain a list of all such files that we've written so
- X * far. Any time we see another, we check the list and
- X * avoid dumping the data again if we've done it once already.
- X */
- X if (hstat.st_nlink > 1) switch (hstat.st_mode & S_IFMT) {
- X register struct link *lp;
- X
- X case S_IFREG: /* Regular file */
- X#ifdef S_IFCTG
- X case S_IFCTG: /* Contigous file */
- X#endif
- X#ifdef S_IFCHR
- X case S_IFCHR: /* Character special file */
- X#endif
- X
- X#ifdef S_IFBLK
- X case S_IFBLK: /* Block special file */
- X#endif
- X
- X#ifdef S_IFIFO
- X case S_IFIFO: /* Fifo special file */
- X#endif
- X
- X /* First quick and dirty. Hashing, etc later FIXME */
- X for (lp = linklist; lp; lp = lp->next) {
- X if (lp->ino == hstat.st_ino &&
- X lp->dev == hstat.st_dev) {
- X /* We found a link. */
- X hstat.st_size = 0;
- X header = start_header(p, &hstat);
- X if (header == NULL) goto badfile;
- X strcpy(header->header.linkname,
- X lp->name);
- X header->header.linkflag = LF_LINK;
- X finish_header(header);
- X /* FIXME: Maybe remove from list after all links found? */
- X return; /* We dumped it */
- X }
- X }
- X
- X /* Not found. Add it to the list of possible links. */
- X lp = (struct link *) malloc( (unsigned)
- X (strlen(p) + sizeof(struct link) - NAMSIZ));
- X if (!lp) {
- X if (!nolinks) {
- X fprintf(stderr,
- X "tar: no memory for links, they will be dumped as separate files\n");
- X nolinks++;
- X }
- X }
- X lp->ino = hstat.st_ino;
- X lp->dev = hstat.st_dev;
- X strcpy(lp->name, p);
- X lp->next = linklist;
- X linklist = lp;
- X }
- X
- X /*
- X * This is not a link to a previously dumped file, so dump it.
- X */
- X switch (hstat.st_mode & S_IFMT) {
- X
- X case S_IFREG: /* Regular file */
- X#ifdef S_IFCTG
- X case S_IFCTG: /* Contigous file */
- X#endif
- X {
- X int f; /* File descriptor */
- X int bufsize, count;
- X register long sizeleft;
- X register union record *start;
- X
- X sizeleft = hstat.st_size;
- X /* Don't bother opening empty, world readable files. */
- X if (sizeleft > 0 || 0444 != (0444 & hstat.st_mode)) {
- X f = open(p, O_RDONLY|O_BINARY);
- X if (f < 0) goto badperror;
- X } else {
- X f = -1;
- X }
- X header = start_header(p, &hstat);
- X if (header == NULL) goto badfile;
- X#ifdef S_IFCTG
- X /* Mark contiguous files, if we support them */
- X if (f_standard && (hstat.st_mode & S_IFMT) == S_IFCTG) {
- X header->header.linkflag = LF_CONTIG;
- X }
- X#endif
- X finish_header(header);
- X while (sizeleft > 0) {
- X start = findrec();
- X bufsize = endofrecs()->charptr - start->charptr;
- X if (sizeleft < bufsize) {
- X /* Last read -- zero out area beyond */
- X bufsize = (int)sizeleft;
- X count = bufsize % RECORDSIZE;
- X if (count)
- X bzero(start->charptr + sizeleft,
- X RECORDSIZE - count);
- X }
- X count = read(f, start->charptr, bufsize);
- X if (count < 0) {
- X annorec(stderr, tar);
- X fprintf(stderr,
- X "read error at byte %ld, reading %d bytes, in file ",
- X hstat.st_size - sizeleft,
- X bufsize);
- X perror(p); /* FIXME */
- X goto padit;
- X }
- X sizeleft -= count;
- X /* This is nonportable (the type of userec's arg). */
- X userec(start+(count-1)/RECORDSIZE);
- X if (count == bufsize) continue;
- X annorec(stderr, tar);
- X fprintf(stderr,
- X "%s: file shrunk by %d bytes, padding with zeros.\n",
- X p, sizeleft);
- X goto padit; /* Short read */
- X }
- X if (f >= 0)
- X (void)close(f);
- X#ifdef AMIGA
- X if (f_archive_set)
- X {
- X if (SmartSetProtection(p, hstat.st_prot |
- X FIBF_ARCHIVE) < 0)
- X {
- X fputs("tar: Error setting archive bit on ", stderr);
- X perror(p);
- X }
- X }
- X#endif
- X break;
- X
- X /*
- X * File shrunk or gave error, pad out tape to match
- X * the size we specified in the header.
- X */
- X padit:
- X abort();
- X }
- X
- X#ifdef S_IFLNK
- X case S_IFLNK: /* Symbolic link */
- X {
- X int size;
- X
- X hstat.st_size = 0; /* Force 0 size on symlink */
- X header = start_header(p, &hstat);
- X if (header == NULL) goto badfile;
- X size = readlink(p, header->header.linkname, NAMSIZ);
- X if (size < 0) goto badperror;
- X if (size == NAMSIZ) {
- X annorec(stderr, tar);
- X fprintf(stderr,
- X "%s: symbolic link too long\n", p);
- X break;
- X }
- X header->header.linkname[size] = '\0';
- X header->header.linkflag = LF_SYMLINK;
- X finish_header(header); /* Nothing more to do to it */
- X }
- X break;
- X#endif
- X
- X case S_IFDIR: /* Directory */
- X {
- X register DIR *dirp;
- X register struct dirent *d;
- X char namebuf[NAMSIZ+2];
- X register int len;
- X int our_device = hstat.st_dev;
- X
- X /* Build new prototype name */
- X strncpy(namebuf, p, sizeof (namebuf));
- X#ifdef AMIGA
- X /*
- X * If user types "" (current dir), make namebuf be ./ - this
- X * will later be stripped.
- X */
- X if (!*namebuf) {
- X strcpy(namebuf, "./");
- X }
- X#endif
- X len = strlen(namebuf);
- X while (len >= 1 && '/' == namebuf[len-1])
- X len--; /* Delete trailing slashes */
- X#ifdef AMIGA
- X if (namebuf[len - 1] != ':') /* no / after : */
- X namebuf[len++] = '/'; /* Now add exactly one back */
- X#else
- X namebuf[len++] = '/'; /* Now add exactly one back */
- X#endif
- X namebuf[len] = '\0'; /* Make sure null-terminated */
- X /*
- X * Output directory header record with permissions
- X * FIXME, do this AFTER files, to avoid R/O dir problems?
- X * If old archive format, don't write record at all.
- X */
- X if (!f_oldarch) {
- X hstat.st_size = 0; /* Force 0 size on dir */
- X /*
- X * If people could really read standard archives,
- X * this should be: (FIXME)
- X header = start_header(f_standard? p: namebuf, &hstat);
- X * but since they'd interpret LF_DIR records as
- X * regular files, we'd better put the / on the name.
- X */
- X header = start_header(namebuf, &hstat);
- X if (header == NULL)
- X goto badfile; /* eg name too long */
- X if (f_standard) {
- X header->header.linkflag = LF_DIR;
- X }
- X finish_header(header); /* Done with directory header */
- X }
- X
- X /* Hack to remove "./" from the front of all the file names */
- X if (len == 2 && namebuf[0] == '.') {
- X len = 0;
- X }
- X
- X /* Now output all the files in the directory */
- X if (f_dironly)
- X break; /* Unless the user says no */
- X errno = 0;
- X dirp = opendir(p);
- X if (!dirp) {
- X if (errno) {
- X perror (p);
- X } else {
- X annorec(stderr, tar);
- X fprintf(stderr, "%s: error opening directory",
- X p);
- X }
- X break;
- X }
- X
- X /* Should speed this up by cd-ing into the dir, FIXME */
- X while (NULL != (d=readdir(dirp))) {
- X /* Skip . and .. */
- X if (d->d_name[0] == '.') {
- X if (d->d_name[1] == '\0') continue;
- X if (d->d_name[1] == '.') {
- X if (d->d_name[2] == '\0') continue;
- X }
- X }
- X if (strlen(d->d_name) + len >= NAMSIZ) {
- X annorec(stderr, tar);
- X fprintf(stderr, "%s%s: name too long\n",
- X namebuf, d->d_name);
- X continue;
- X }
- X strcpy(namebuf+len, d->d_name);
- X dump_file(namebuf, our_device);
- X }
- X
- X closedir(dirp);
- X#ifdef AMIGA
- X if (f_archive_set)
- X {
- X if (SmartSetProtection(p, hstat.st_prot |
- X FIBF_ARCHIVE) < 0)
- X {
- X fputs("tar: Error setting archive bit on ", stderr);
- X perror(p);
- X }
- X }
- X#endif
- X }
- X break;
- X
- X#ifdef S_IFCHR
- X case S_IFCHR: /* Character special file */
- X type = LF_CHR;
- X goto easy;
- X#endif
- X
- X#ifdef S_IFBLK
- X case S_IFBLK: /* Block special file */
- X type = LF_BLK;
- X goto easy;
- X#endif
- X
- X#ifdef S_IFIFO
- X case S_IFIFO: /* Fifo special file */
- X type = LF_FIFO;
- X#endif
- X
- X easy:
- X if (!f_standard) goto unknown;
- X
- X hstat.st_size = 0; /* Force 0 size */
- X header = start_header(p, &hstat);
- X if (header == NULL) goto badfile; /* eg name too long */
- X
- X header->header.linkflag = type;
- X if (type != LF_FIFO) {
- X to_oct((long) major(hstat.st_rdev), 8,
- X header->header.devmajor);
- X to_oct((long) minor(hstat.st_rdev), 8,
- X header->header.devminor);
- X }
- X
- X finish_header(header);
- X break;
- X
- X default:
- X unknown:
- X annorec(stderr, tar);
- X fprintf(stderr,
- X "%s: Unknown file type; file ignored.\n", p);
- X break;
- X }
- X}
- X
- X
- X/*
- X * Make a header block for the file name whose stat info is st .
- X * Return header pointer for success, NULL if the name is too long.
- X */
- Xunion record *
- Xstart_header(name, st)
- X char *name;
- X register struct stat *st;
- X{
- X register union record *header;
- X char newname[NAMSIZ+2];
- X header = (union record *) findrec();
- X bzero(header->charptr, sizeof(*header)); /* XXX speed up */
- X
- X /*
- X * Check the file name and put it in the record.
- X */
- X#ifdef AMIGA
- X cvtAmi2UNIX(name, newname);
- X name = newname; /* point name at newname, but leave orig string alone */
- X#else
- X while ('/' == *name) {
- X static int warned_once = 0;
- X
- X name++; /* Force relative path */
- X if (!warned_once++) {
- X annorec(stderr, tar);
- X fprintf(stderr,
- X "Removing leading / from absolute path names in the archive.\n");
- X }
- X }
- X#endif
- X strcpy(header->header.name, name);
- X if (header->header.name[NAMSIZ-1]) {
- X annorec(stderr, tar);
- X fprintf(stderr, "%s: name too long\n", name);
- X return NULL;
- X }
- X
- X to_oct((long) (st->st_mode & ~S_IFMT),
- X 8, header->header.mode);
- X to_oct((long) st->st_uid, 8, header->header.uid);
- X to_oct((long) st->st_gid, 8, header->header.gid);
- X to_oct((long) st->st_size, 1+12, header->header.size);
- X to_oct((long) st->st_mtime, 1+12, header->header.mtime);
- X /* header->header.linkflag is left as null */
- X#ifdef AMIGA
- X strcpy(header->header.magic_cookie, "AmigaTar");
- X to_hex(st->st_prot, header->header.amiga_modes);
- X memset(header->header.comment, '\0', sizeof(header->header.comment));
- X strcpy(header->header.comment, st->st_comment);
- X to_hex(st->st_date.ds_Days, header->header.ds_Days);
- X to_hex(st->st_date.ds_Minute, header->header.ds_Minute);
- X to_hex(st->st_date.ds_Tick, header->header.ds_Tick);
- X#endif
- X#ifndef NONAMES
- X /* Fill in new Unix Standard fields if desired. */
- X if (f_standard) {
- X header->header.linkflag = LF_NORMAL; /* New default */
- X strcpy(header->header.magic, TMAGIC); /* Mark as Unix Std */
- X finduname(header->header.uname, st->st_uid);
- X findgname(header->header.gname, st->st_gid);
- X }
- X#endif
- X return header;
- X}
- X
- X/*
- X * Finish off a filled-in header block and write it out.
- X * We also print the file name and/or full info if verbose is on.
- X */
- Xvoid
- Xfinish_header(header)
- X register union record *header;
- X{
- X register int i, sum;
- X register char *p;
- X
- X bcopy(CHKBLANKS, header->header.chksum, sizeof(header->header.chksum));
- X
- X sum = 0;
- X p = header->charptr;
- X for (i = sizeof(*header); --i >= 0; ) {
- X /*
- X * We can't use unsigned char here because of old compilers,
- X * e.g. V7.
- X */
- X sum += 0xFF & *p++;
- X }
- X
- X /*
- X * Fill in the checksum field. It's formatted differently
- X * from the other fields: it has [6] digits, a null, then a
- X * space -- rather than digits, a space, then a null.
- X * We use to_oct then write the null in over to_oct's space.
- X * The final space is already there, from checksumming, and
- X * to_oct doesn't modify it.
- X *
- X * This is a fast way to do:
- X * (void) sprintf(header->header.chksum, "%6o", sum);
- X */
- X to_oct((long) sum, 8, header->header.chksum);
- X header->header.chksum[6] = '\0'; /* Zap the space */
- X
- X userec(header);
- X
- X if (f_verbose) {
- X /* These globals are parameters to print_header, sigh */
- X head = header;
- X /* hstat is already set up */
- X head_standard = f_standard;
- X print_header(stderr);
- X }
- X
- X return;
- X}
- X
- X
- X/*
- X * Quick and dirty octal conversion.
- X * Converts long "value" into a "digs"-digit field at "where",
- X * including a trailing space and room for a null. "digs"==3 means
- X * 1 digit, a space, and room for a null.
- X *
- X * We assume the trailing null is already there and don't fill it in.
- X * This fact is used by start_header and finish_header, so don't change it!
- X *
- X * This should be equivalent to:
- X * (void) sprintf(where, "%*lo ", digs-2, value);
- X * except that sprintf fills in the trailing null and we don't.
- X */
- Xvoid
- Xto_oct(value, digs, where)
- X register long value;
- X register int digs;
- X register char *where;
- X{
- X
- X --digs; /* Trailing null slot is left alone */
- X where[--digs] = ' '; /* Put in the space, though */
- X
- X /* Produce the digits -- at least one */
- X do {
- X where[--digs] = '0' + (char)(value & 7); /* one octal digit */
- X value >>= 3;
- X } while (digs > 0 && value != 0);
- X
- X /* Leading spaces, if necessary */
- X while (digs > 0)
- X where[--digs] = ' ';
- X
- X}
- X
- X
- X/*
- X * Write the EOT record(s).
- X * We actually zero at least one record, through the end of the block.
- X * Old tar writes garbage after two zeroed records -- and PDtar used to.
- X */
- Xwrite_eot()
- X{
- X union record *p;
- X int bufsize;
- X
- X p = findrec();
- X bufsize = endofrecs()->charptr - p->charptr;
- X bzero(p->charptr, bufsize);
- X userec(p);
- X}
- X
- X#ifdef AMIGA
- X/*
- X * 32-bit to 8 ascii chars as hex plus null term
- X */
- Xvoid
- Xto_hex(u_long val, char *p)
- X{
- X int i, nibble;
- X
- X p += 8; /* point to last char */
- X *p = '\0'; /* null term */
- X for (i = 0; i < 8; i++)
- X {
- X nibble = val & 0xf;
- X *--p = (nibble > 9) ? (nibble - 10) + 'a' : nibble + '0';
- X val >>= 4;
- X }
- X}
- X#endif
- END_OF_FILE
- if test 15979 -ne `wc -c <'create.c'`; then
- echo shar: \"'create.c'\" unpacked with wrong size!
- fi
- # end of 'create.c'
- fi
- if test -f 'extract.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'extract.c'\"
- else
- echo shar: Extracting \"'extract.c'\" \(13710 characters\)
- sed "s/^X//" >'extract.c' <<'END_OF_FILE'
- X/*
- X * Extract files from a tar archive.
- X *
- X * Written 19 Nov 1985 by John Gilmore, ihnp4!hoptoad!gnu.
- X *
- X * @(#) extract.c 1.32 87/11/11 Public Domain - gnu
- X */
- X
- X#include <stdio.h>
- X#include <errno.h>
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X
- X#ifdef BSD42
- X#include <sys/file.h>
- X#endif
- X
- X#ifdef USG
- X#include <fcntl.h>
- X#endif
- X
- X#if defined(MSDOS) || defined(AMIGA)
- X#include <fcntl.h>
- X#endif /* MSDOS */
- X
- X/*
- X * Some people don't have a #define for these.
- X */
- X#ifndef O_BINARY
- X#define O_BINARY 0
- X#endif
- X#ifndef O_NDELAY
- X#define O_NDELAY 0
- X#endif
- X
- X#ifdef NO_OPEN3
- X/* We need the #define's even though we don't use them. */
- X#include "open3.h"
- X#endif
- X
- X#ifdef EMUL_OPEN3
- X/* Simulated 3-argument open for systems that don't have it */
- X#include "open3.h"
- X#endif
- X
- Xextern int errno; /* From libc.a */
- Xextern time_t time(); /* From libc.a */
- Xextern char *index(); /* From libc.a or port.c */
- X
- X#include "tar.h"
- X#include "port.h"
- X
- Xextern union record *head; /* Points to current tape header */
- Xextern struct stat hstat; /* Stat struct corresponding */
- Xextern int head_standard; /* Tape header is in ANSI format */
- X
- Xextern void print_header();
- Xextern void skip_file();
- Xextern void pr_mkdir();
- X
- Xint make_dirs(); /* Makes required directories */
- X#ifdef AMIGA
- Xextern int made_on_amiga; /* decode_header() sets this if tar
- X * was made on Amiga. Passing this
- X * as a param would change too much
- X * code so we make it a global */
- X#endif
- X
- Xstatic time_t now = 0; /* Current time */
- Xstatic we_are_root = 0; /* True if our effective uid == 0 */
- Xstatic int notumask = ~0; /* Masks out bits user doesn't want */
- X
- X/*
- X * Set up to extract files.
- X */
- Xextr_init()
- X{
- X int ourmask;
- X
- X now = time((time_t *)0);
- X if (geteuid() == 0)
- X we_are_root = 1;
- X
- X /*
- X * We need to know our umask. But if f_use_protection is set,
- X * leave our kernel umask at 0, and our "notumask" at ~0.
- X */
- X ourmask = umask(0); /* Read it */
- X if (!f_use_protection) {
- X (void) umask (ourmask); /* Set it back how it was */
- X notumask = ~ourmask; /* Make umask override permissions */
- X }
- X}
- X
- X
- X/*
- X * Extract a file from the archive.
- X */
- Xvoid
- Xextract_archive()
- X{
- X register char *data;
- X int fd, check, namelen, written, openflag;
- X long size;
- X time_t acc_upd_times[2];
- X register int skipcrud;
- X#ifdef AMIGA
- X int protection; /* protection bits */
- X#endif
- X
- X saverec(&head); /* Make sure it sticks around */
- X userec(head); /* And go past it in the archive */
- X decode_header(head, &hstat, &head_standard, 1); /* Snarf fields */
- X
- X /* Print the record from 'head' and 'hstat' */
- X if (f_verbose)
- X print_header(stdout);
- X
- X /*
- X * Check for fully specified pathnames and other atrocities.
- X *
- X * Note, we can't just make a pointer to the new file name,
- X * since saverec() might move the header and adjust "head".
- X * We have to start from "head" every time we want to touch
- X * the header record.
- X */
- X skipcrud = 0;
- X while ('/' == head->header.name[skipcrud]) {
- X static int warned_once = 0;
- X
- X skipcrud++; /* Force relative path */
- X if (!warned_once++) {
- X annorec(stderr, tar);
- X fprintf(stderr,
- X "Removing leading / from absolute path names in the archive.\n");
- X }
- X }
- X#ifdef AMIGA
- X cvtUNIX2Ami(skipcrud + head->header.name);
- X#endif
- X switch (head->header.linkflag) {
- X
- X default:
- X annofile(stderr, tar);
- X fprintf(stderr,
- X "Unknown file type '%c' for %s, extracted as normal file\n",
- X head->header.linkflag, skipcrud+head->header.name);
- X /* FALL THRU */
- X
- X case LF_OLDNORMAL:
- X case LF_NORMAL:
- X case LF_CONTIG:
- X /*
- X * Appears to be a file.
- X * See if it's really a directory.
- X */
- X namelen = strlen(skipcrud+head->header.name)-1;
- X if (head->header.name[skipcrud+namelen] == '/')
- X goto really_dir;
- X
- X /* FIXME, deal with protection issues */
- X again_file:
- X#if defined(AMIGA) && defined(LATTICE) /* open w/O_EXCL is broken, sigh */
- X openflag = O_BINARY|O_NDELAY|O_WRONLY|O_APPEND|O_CREAT|O_TRUNC;
- X#else
- X openflag = f_keep?
- X O_BINARY|O_NDELAY|O_WRONLY|O_APPEND|O_CREAT|O_EXCL:
- X O_BINARY|O_NDELAY|O_WRONLY|O_APPEND|O_CREAT|O_TRUNC;
- X#endif
- X
- X#ifdef O_CTG
- X /*
- X * Contiguous files (on the Masscomp) have to specify
- X * the size in the open call that creates them.
- X */
- X if (head->header.lnkflag == LF_CONTIG)
- X fd = open(skipcrud+head->header.name, openflag | O_CTG,
- X hstat.st_mode, hstat.st_size);
- X else
- X#endif
- X {
- X#ifdef NO_OPEN3
- X /*
- X * On raw V7 we won't let them specify -k (f_keep), but
- X * we just bull ahead and create the files.
- X */
- X fd = creat(skipcrud+head->header.name,
- X hstat.st_mode);
- X#else
- X /*
- X * With 3-arg open(), we can do this up right.
- X */
- X#if defined(AMIGA) && defined(LATTICE)
- X if (f_keep && !access(skipcrud+head->header.name,
- X O_RDONLY))
- X {
- X fd = -1;
- X errno = EEXIST;
- X }
- X else
- X fd = open(skipcrud+head->header.name, openflag,
- X hstat.st_mode);
- X#endif
- X#endif
- X }
- X
- X if (fd < 0) {
- X if (make_dirs(skipcrud+head->header.name))
- X goto again_file;
- X annofile(stderr, tar);
- X fprintf(stderr, "Could not make file ");
- X perror(skipcrud+head->header.name);
- X skip_file((long)hstat.st_size);
- X goto quit;
- X }
- X
- X for (size = hstat.st_size;
- X size > 0;
- X size -= written) {
- X /*
- X * Locate data, determine max length
- X * writeable, write it, record that
- X * we have used the data, then check
- X * if the write worked.
- X */
- X data = findrec()->charptr;
- X if (data == NULL) { /* Check it... */
- X annorec(stderr, tar);
- X fprintf(stderr, "Unexpected EOF on archive file\n");
- X break;
- X }
- X written = endofrecs()->charptr - data;
- X if (written > size) written = size;
- X errno = 0;
- X check = write(fd, data, written);
- X /*
- X * The following is in violation of strict
- X * typing, since the arg to userec
- X * should be a struct rec *. FIXME.
- X */
- X userec(data + written - 1);
- X if (check == written) continue;
- X /*
- X * Error in writing to file.
- X * Print it, skip to next file in archive.
- X */
- X annofile(stderr, tar);
- X fprintf(stderr,
- X "Tried to write %d bytes to file, could only write %d:\n",
- X written, check);
- X perror(skipcrud+head->header.name);
- X skip_file((long)(size - written));
- X break; /* Still do the close, mod time, chmod, etc */
- X }
- X
- X check = close(fd);
- X if (check < 0) {
- X annofile(stderr, tar);
- X fprintf(stderr, "Error while closing ");
- X perror(skipcrud+head->header.name);
- X }
- X
- X set_filestat:
- X#ifdef AMIGA
- X /*
- X * Set the comment on the file
- X */
- X if (made_on_amiga)
- X {
- X if (SmartSetComment(skipcrud+head->header.name,
- X hstat.st_comment) < 0)
- X {
- X annofile(stderr, tar);
- X fputs("failed to set comment on ", stderr);
- X perror(skipcrud+head->header.name);
- X }
- X }
- X#endif
- X /*
- X * Set the modified time of the file.
- X *
- X * Note that we set the accessed time to "now", which
- X * is really "the time we started extracting files".
- X */
- X if (!f_modified) {
- X acc_upd_times[0] = now; /* Accessed now */
- X acc_upd_times[1] = hstat.st_mtime; /* Mod'd */
- X#ifdef AMIGA
- X if (made_on_amiga) {
- X if (utime_from_stamp(skipcrud+head->header.name,
- X &(hstat.st_date)) < 0) {
- X annofile(stderr, tar);
- X fputs("utime failed:", stderr);
- X perror(skipcrud+head->header.name);
- X }
- X } else {
- X#endif
- X if (utime(skipcrud+head->header.name,
- X acc_upd_times) < 0) {
- X annofile(stderr, tar);
- X fputs("utime failed:", stderr);
- X perror(skipcrud+head->header.name);
- X }
- X#ifdef AMIGA
- X }
- X#endif
- X }
- X
- X /*
- X * If we are root, set the owner and group of the extracted
- X * file. This does what is wanted both on real Unix and on
- X * System V. If we are running as a user, we extract as that
- X * user; if running as root, we extract as the original owner.
- X */
- X if (we_are_root) {
- X if (chown(skipcrud+head->header.name, hstat.st_uid,
- X hstat.st_gid) < 0) {
- X annofile(stderr, tar);
- X perror(skipcrud+head->header.name);
- X }
- X }
- X
- X /*
- X * If '-k' is not set, open() or creat() could have saved
- X * the permission bits from a previously created file,
- X * ignoring the ones we specified.
- X * Even if -k is set, if the file has abnormal
- X * mode bits, we must chmod since writing or chown() has
- X * probably reset them.
- X *
- X * If -k is set, we know *we* created this file, so the mode
- X * bits were set by our open(). If the file is "normal", we
- X * skip the chmod. This works because we did umask(0) if -p
- X * is set, so umask will have left the specified mode alone.
- X */
- X#ifdef AMIGA
- X /*
- X * open() ignores modes, so always do this unless
- X */
- X if (made_on_amiga)
- X protection = hstat.st_prot & ~FIBF_ARCHIVE;
- X else
- X protection = ~((hstat.st_mode >> 5) | 1) & 0xf;
- X if (SmartSetProtection(skipcrud+head->header.name,
- X protection) < 0)
- X {
- X annofile(stderr, tar);
- X fputs("failed to set protection on ", stderr);
- X perror(skipcrud+head->header.name);
- X }
- X#else
- X if ((!f_keep)
- X || (hstat.st_mode & (S_ISUID|S_ISGID|S_ISVTX))) {
- X if (chmod(skipcrud+head->header.name,
- X notumask & (int)hstat.st_mode) < 0) {
- X annofile(stderr, tar);
- X perror(skipcrud+head->header.name);
- X }
- X }
- X#endif
- X
- X quit:
- X break;
- X
- X case LF_LINK:
- X again_link:
- X check = link (head->header.linkname,
- X skipcrud+head->header.name);
- X if (check == 0)
- X break;
- X if (make_dirs(skipcrud+head->header.name))
- X goto again_link;
- X annofile(stderr, tar);
- X fprintf(stderr, "Could not link %s to ",
- X skipcrud+head->header.name);
- X perror(head->header.linkname);
- X break;
- X
- X#ifdef S_IFLNK
- X case LF_SYMLINK:
- X again_symlink:
- X check = symlink(head->header.linkname,
- X skipcrud+head->header.name);
- X /* FIXME, don't worry uid, gid, etc... */
- X if (check == 0)
- X break;
- X if (make_dirs(skipcrud+head->header.name))
- X goto again_symlink;
- X annofile(stderr, tar);
- X fprintf(stderr, "Could not create symlink ");
- X perror(head->header.linkname);
- X break;
- X#endif
- X
- X#ifdef S_IFCHR
- X case LF_CHR:
- X hstat.st_mode |= S_IFCHR;
- X goto make_node;
- X#endif
- X
- X#ifdef S_IFBLK
- X case LF_BLK:
- X hstat.st_mode |= S_IFBLK;
- X goto make_node;
- X#endif
- X
- X#ifdef S_IFIFO
- X /* If local system doesn't support FIFOs, use default case */
- X case LF_FIFO:
- X hstat.st_mode |= S_IFIFO;
- X hstat.st_rdev = 0; /* FIXME, do we need this? */
- X goto make_node;
- X#endif
- X
- X make_node:
- X check = mknod(skipcrud+head->header.name,
- X (int) hstat.st_mode, (int) hstat.st_rdev);
- X if (check != 0) {
- X if (make_dirs(skipcrud+head->header.name))
- X goto make_node;
- X annofile(stderr, tar);
- X fprintf(stderr, "Could not make ");
- X perror(skipcrud+head->header.name);
- X break;
- X };
- X goto set_filestat;
- X
- X case LF_DIR:
- X namelen = strlen(skipcrud+head->header.name)-1;
- X really_dir:
- X /* Check for trailing /, and zap as many as we find. */
- X while (namelen && head->header.name[skipcrud+namelen] == '/')
- X head->header.name[skipcrud+namelen--] = '\0';
- X
- X again_dir:
- X#ifdef AMIGA
- X /* don't mkdir("", mode) */
- X check = 0;
- X if (*(skipcrud+head->header.name))
- X#endif
- X check = mkdir(skipcrud+head->header.name,
- X 0300 | (int)hstat.st_mode);
- X if (check != 0) {
- X if (make_dirs(skipcrud+head->header.name))
- X goto again_dir;
- X /* If we're trying to create '.', let it be. */
- X if (head->header.name[skipcrud+namelen] == '.' &&
- X (namelen==0 ||
- X head->header.name[skipcrud+namelen-1]=='/'))
- X goto check_perms;
- X annofile(stderr, tar);
- X fprintf(stderr, "Could not make directory ");
- X perror(skipcrud+head->header.name);
- X break;
- X }
- X
- X check_perms:
- X if (0300 != (0300 & (int) hstat.st_mode)) {
- X hstat.st_mode |= 0300;
- X annofile(stderr, tar);
- X fprintf(stderr,
- X "Added write & execute permission to directory %s\n",
- X skipcrud+head->header.name);
- X }
- X
- X goto set_filestat;
- X /* FIXME, Remember timestamps for after files created? */
- X /* FIXME, change mode after files created (if was R/O dir) */
- X
- X }
- X
- X /* We don't need to save it any longer. */
- X saverec((union record **) 0); /* Unsave it */
- X}
- X
- X/*
- X * After a file/link/symlink/dir creation has failed, see if
- X * it's because some required directory was not present, and if
- X * so, create all required dirs.
- X */
- Xint
- Xmake_dirs(pathname)
- X char *pathname;
- X{
- X char *p; /* Points into path */
- X int madeone = 0; /* Did we do anything yet? */
- X int save_errno = errno; /* Remember caller's errno */
- X int check;
- X
- X if (errno != ENOENT)
- X return 0; /* Not our problem */
- X#if defined(AMIGA) && defined(LATTICE)
- X /*
- X * ARRRRGGGGHHHH! If delete bit is not set, open fails with ENOENT.
- X * I think it should be EPERM. So we check for the file's existance
- X * here and return if it does exist.
- X */
- X if (!access(pathname, O_RDONLY))
- X {
- X errno = EPERM; /* perror should say "Permission Denied"
- X * but, says something stupid instead */
- X return(0); /* Not our problem */
- X }
- X#endif
- X for (p = index(pathname, '/'); p != NULL; p = index(p+1, '/')) {
- X /* Avoid mkdir of empty string, if leading or double '/' */
- X if (p == pathname || p[-1] == '/')
- X continue;
- X /* Avoid mkdir where last part of path is '.' */
- X if (p[-1] == '.' && (p == pathname+1 || p[-2] == '/'))
- X continue;
- X *p = 0; /* Truncate the path there */
- X check = mkdir (pathname, 0777); /* Try to create it as a dir */
- X if (check == 0) {
- X /* Fix ownership */
- X if (we_are_root) {
- X if (chown(pathname, hstat.st_uid,
- X hstat.st_gid) < 0) {
- X annofile(stderr, tar);
- X perror(pathname);
- X }
- X }
- X pr_mkdir(pathname, p-pathname, notumask&0777, stdout);
- X madeone++; /* Remember if we made one */
- X *p = '/';
- X continue;
- X }
- X *p = '/';
- X if (errno == EEXIST) /* Directory already exists */
- X continue;
- X /*
- X * Some other error in the mkdir. We return to the caller.
- X */
- X break;
- X }
- X
- X errno = save_errno; /* Restore caller's errno */
- X return madeone; /* Tell them to retry if we made one */
- X}
- END_OF_FILE
- if test 13710 -ne `wc -c <'extract.c'`; then
- echo shar: \"'extract.c'\" unpacked with wrong size!
- fi
- # end of 'extract.c'
- fi
- if test -f 'port.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'port.c'\"
- else
- echo shar: Extracting \"'port.c'\" \(12968 characters\)
- sed "s/^X//" >'port.c' <<'END_OF_FILE'
- X/*
- X * @(#)port.c 1.15 87/11/05 Public Domain, by John Gilmore, 1986
- X *
- X * These are routines not available in all environments.
- X *
- X * I know this introduces an extra level of subroutine calls and is
- X * slightly slower. Frankly, my dear, I don't give a damn. Let the
- X * Missed-Em Vee losers suffer a little. This software is proud to
- X * have been written on a BSD system.
- X */
- X#ifdef AMIGA
- X#include <stdlib.h>
- X#endif
- X
- X#include <stdio.h>
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X#include <signal.h>
- X#include <errno.h>
- X
- X#if defined(MSDOS) || defined(AMIGA)
- X#include <fcntl.h>
- X#else
- X#include <sys/file.h>
- X#endif
- X
- X#include "tar.h"
- X
- Xextern char **environ;
- X
- X#ifndef NULL
- X#define NULL 0
- X#endif
- X
- X/*
- X * Some people (e.g. V7) don't have a #define for these.
- X */
- X#ifndef O_BINARY
- X#define O_BINARY 0
- X#endif
- X#ifndef O_RDONLY
- X#define O_RDONLY 0
- X#endif
- X
- X
- X#include "port.h"
- X
- X
- X/*
- X * Some computers are not so crass as to align themselves into the BSD
- X * or USG camps. If a system supplies all of the routines we fake here,
- X * add it to the list in the #ifndefs below and it'll all be skipped.
- X * Make sure to add a matching #endif at the end of the file!
- X *
- X * We are avoiding #if defined() here for the sake of Minix, which comes
- X * with the severely broken Amsterdam Compiler Kit. Thanks, Andy!
- X */
- X#ifndef mc300
- X#ifndef mc500
- X#ifndef mc700
- X
- X
- X#ifndef BSD42
- X/*
- X * lstat() is a stat() which does not follow symbolic links.
- X * If there are no symbolic links, just use stat().
- X */
- Xint
- Xlstat (path, buf)
- X char *path;
- X struct stat *buf;
- X{
- X extern int stat ();
- X return (stat (path, buf));
- X}
- X
- X/*
- X * valloc() does a malloc() on a page boundary. On some systems,
- X * this can make large block I/O more efficient.
- X */
- Xchar *
- Xvalloc (size)
- X unsigned size;
- X{
- X#ifndef AMIGA
- X extern char *malloc ();
- X#endif
- X return (malloc (size));
- X}
- X
- X/*
- X * NMKDIR.C
- X *
- X * Written by Robert Rother, Mariah Corporation, August 1985.
- X *
- X * I wrote this out of shear disgust with myself because I couldn't
- X * figure out how to do this in /bin/sh.
- X *
- X * If you want it, it's yours. All I ask in return is that if you
- X * figure out how to do this in a Bourne Shell script you send me
- X * a copy.
- X * sdcsvax!rmr or rmr@uscd
- X*
- X* Severely hacked over by John Gilmore to make a 4.2BSD compatible
- X* subroutine. 11Mar86; hoptoad!gnu
- X*
- X* Modified by rmtodd@uokmax 6-28-87 -- when making an already existing dir,
- X* subroutine didn't return EEXIST. It does now.
- X*/
- X
- X/*
- X * Make a directory. Compatible with the mkdir() system call on 4.2BSD.
- X */
- X#if !defined(MSDOS) && !defined(AMIGA)
- Xint
- Xmkdir(dpath, dmode)
- X char *dpath;
- X int dmode;
- X{
- X int cpid, status;
- X struct stat statbuf;
- X extern int errno;
- X
- X if (stat(dpath,&statbuf) == 0) {
- X errno = EEXIST; /* Stat worked, so it already exists */
- X return -1;
- X }
- X
- X /* If stat fails for a reason other than non-existence, return error */
- X if (errno != ENOENT) return -1;
- X
- X switch (cpid = fork()) {
- X
- X case -1: /* Error in fork() */
- X return(-1); /* Errno is set already */
- X
- X case 0: /* Child process */
- X /*
- X * Cheap hack to set mode of new directory. Since this
- X * child process is going away anyway, we zap its umask.
- X * FIXME, this won't suffice to set SUID, SGID, etc. on this
- X * directory. Does anybody care?
- X */
- X status = umask(0); /* Get current umask */
- X status = umask(status | (0777 & ~dmode)); /* Set for mkdir */
- X execl("/bin/mkdir", "mkdir", dpath, (char *)0);
- X _exit(-1); /* Can't exec /bin/mkdir */
- X
- X default: /* Parent process */
- X while (cpid != wait(&status)) ; /* Wait for kid to finish */
- X }
- X
- X if (TERM_SIGNAL(status) != 0 || TERM_VALUE(status) != 0) {
- X errno = EIO; /* We don't know why, but */
- X return -1; /* /bin/mkdir failed */
- X }
- X
- X return 0;
- X}
- X#endif /* MSDOS */
- X#endif
- X
- X/* This next bit is called "doing OR on Minix cpp", e.g. without defined(). */
- X#undef WANTSTRING
- X#ifdef USG
- X#define WANTSTRING
- X#endif
- X#ifdef MSDOS
- X#define WANTSTRING
- X#endif
- X#ifdef AMIGA
- X#define WANTSTRING
- X#endif
- X
- X#ifdef WANTSTRING
- X/*
- X * Translate V7 style into Sys V style.
- X */
- X#include <string.h>
- X#ifndef AMIGA
- X#include <memory.h>
- X#endif
- X
- Xchar *
- Xindex (s, c)
- X char *s;
- X int c;
- X{
- X return (strchr (s, c));
- X}
- X
- Xvoid
- Xbcopy (s1, s2, n)
- X char *s1, *s2;
- X int n;
- X{
- X (void) memcpy (s2, s1, n);
- X}
- X
- Xvoid
- Xbzero (s1, n)
- X char *s1;
- X int n;
- X{
- X (void) memset(s1, 0, n);
- X}
- X
- Xint
- Xbcmp(s1, s2, n)
- X char *s1, *s2;
- X int n;
- X{
- X return memcmp(s1, s2, n);
- X}
- X#endif
- X
- X#ifdef MINIX
- X/* Minix has bcopy but not bzero, and no memset. Thanks, Andy. */
- Xvoid
- Xbzero (s1, n)
- X register char *s1;
- X register int n;
- X{
- X while (n--) *s1++ = '\0';
- X}
- X
- X/* It also has no bcmp() */
- Xint
- Xbcmp (s1, s2, n)
- X register char *s1,*s2;
- X register int n;
- X{
- X for ( ; n-- ; ++s1, ++s2) {
- X if (*s1 != *s2) return *s1 - *s2;
- X }
- X return 0;
- X}
- X
- X/*
- X * Groan, Minix doesn't have execlp either!
- X *
- X * execlp(file,arg0,arg1...argn,(char *)NULL)
- X * exec a program, automatically searching for the program through
- X * all the directories on the PATH.
- X *
- X * This version is naive about variable argument lists, it assumes
- X * a straightforward C calling sequence. If your system has odd stacks
- X * *and* doesn't have execlp, YOU get to fix it.
- X */
- Xint
- Xexeclp(filename, arg0)
- X char *filename, *arg0;
- X{
- X extern char *malloc(), *getenv(), *index();
- X extern int errno;
- X register char *p, *path;
- X char **argstart = &arg0;
- X register char *fnbuffer;
- X struct stat statbuf;
- X
- X if ((p = getenv("PATH")) == NULL) {
- X /* couldn't find path variable -- try to exec given filename */
- X return execve(filename, argstart, environ);
- X }
- X
- X /*
- X * make a place to build the filename. We malloc larger than we
- X * need, but we know it will fit in this.
- X */
- X fnbuffer = malloc( strlen(p) + 1 + strlen(filename) );
- X if (fnbuffer == NULL) {
- X errno = ENOMEM;
- X return -1;
- X }
- X
- X /*
- X * try each component of the path to see if the file's there
- X * and executable.
- X */
- X for (path = p ; path ; path = p) {
- X /* construct full path name to try */
- X if ((p = index(path,':')) == NULL) {
- X strcpy(fnbuffer, path);
- X } else {
- X strncpy(fnbuffer, path, p-path);
- X fnbuffer[p-path] = '\0';
- X p++; /* Skip : for next time */
- X }
- X if (strlen(fnbuffer) != 0)
- X strcat(fnbuffer,"/");
- X strcat(fnbuffer,filename);
- X
- X /* check to see if file is there and is a normal file */
- X if (stat(fnbuffer, &statbuf) < 0) {
- X if (errno == ENOENT)
- X continue; /* file not there,keep on looking */
- X else
- X goto fail; /* failed for some reason, return */
- X }
- X if ( (statbuf.st_mode & S_IFMT) != S_IFREG) continue;
- X
- X if (execve(fnbuffer, argstart, environ) < 0
- X && errno != ENOENT
- X && errno != ENOEXEC) {
- X /* failed, for some other reason besides "file
- X * not found" or "not a.out format"
- X */
- X goto fail;
- X }
- X
- X /*
- X * If we got error ENOEXEC, the file is executable but is
- X * not an object file. Try to execute it as a shell script,
- X * returning error if we can't execute /bin/sh.
- X *
- X * FIXME, this code is broken in several ways. Shell
- X * scripts should not in general be executed by the user's
- X * SHELL variable program. On more mature systems, the
- X * script can specify with #!/bin/whatever. Also, this
- X * code clobbers argstart[-1] if the exec of the shell
- X * fails.
- X */
- X if (errno == ENOEXEC) {
- X char *shell;
- X
- X /* Try to execute command "sh arg0 arg1 ..." */
- X if ((shell = getenv("SHELL")) == NULL)
- X shell = "/bin/sh";
- X argstart[-1] = shell;
- X argstart[0] = fnbuffer;
- X execve(shell, &argstart[-1], environ);
- X goto fail; /* Exec didn't work */
- X }
- X
- X /*
- X * If we succeeded, the execve() doesn't return, so we
- X * can only be here is if the file hasn't been found yet.
- X * Try the next place on the path.
- X */
- X }
- X
- X /* all attempts failed to locate the file. Give up. */
- X errno = ENOENT;
- X
- Xfail:
- X free(fnbuffer);
- X return -1;
- X}
- X#endif /* MINIX */
- X
- X
- X#ifdef EMUL_OPEN3
- X#include "open3.h"
- X/*
- X * open3 -- routine to emulate the 3-argument open system
- X * call that is present in most modern Unix systems.
- X * This version attempts to support all the flag bits except for O_NDELAY
- X * and O_APPEND, which are silently ignored. The emulation is not as efficient
- X * as the real thing (at worst, 4 system calls instead of one), but there's
- X * not much I can do about that.
- X *
- X * Written 6/10/87 by rmtodd@uokmax
- X *
- X * open3(path, flag, mode)
- X * Attempts to open the file specified by
- X * the given pathname. The following flag bits (#defined in tar.h)
- X * specify options to the routine:
- X * O_RDONLY file open for read only
- X * O_WRONLY file open for write only
- X * O_RDWR file open for both read & write
- X * (Needless to say, you should only specify one of the above).
- X * O_CREAT file is created with specified mode if it needs to be.
- X * O_TRUNC if file exists, it is truncated to 0 bytes
- X * O_EXCL used with O_CREAT--routine returns error if file exists
- X * Function returns file descriptor if successful, -1 and errno if not.
- X */
- X
- X/*
- X * array to give arguments to access for various modes
- X * FIXME, this table depends on the specific integer values of O_XXX,
- X * and also contains integers (args to 'access') that should be #define's.
- X */
- Xstatic int modes[] =
- X {
- X 04, /* O_RDONLY */
- X 02, /* O_WRONLY */
- X 06, /* O_RDWR */
- X 06, /* invalid but we'd better cope -- O_WRONLY+O_RDWR */
- X };
- X
- X/* Shut off the automatic emulation of open(), we'll need it. */
- X#undef open
- X
- Xint
- Xopen3(path, flags, mode)
- Xchar *path;
- Xint flags, mode;
- X{
- X extern int errno;
- X int exists = 1;
- X int call_creat = 0;
- X int fd;
- X /*
- X * We actually do the work by calling the open() or creat() system
- X * call, depending on the flags. Call_creat is true if we will use
- X * creat(), false if we will use open().
- X */
- X
- X /*
- X * See if the file exists and is accessible in the requested mode.
- X *
- X * Strictly speaking we shouldn't be using access, since access checks
- X * against real uid, and the open call should check against euid.
- X * Most cases real uid == euid, so it won't matter. FIXME.
- X * FIXME, the construction "flags & 3" and the modes table depends
- X * on the specific integer values of the O_XXX #define's. Foo!
- X */
- X if (access(path,modes[flags & 3]) < 0) {
- X if (errno == ENOENT) {
- X /* the file does not exist */
- X exists = 0;
- X } else {
- X /* probably permission violation */
- X if (flags & O_EXCL) {
- X /* Oops, the file exists, we didn't want it. */
- X /* No matter what the error, claim EEXIST. */
- X errno = EEXIST;
- X }
- X return -1;
- X }
- X }
- X
- X /* if we have the O_CREAT bit set, check for O_EXCL */
- X if (flags & O_CREAT) {
- X if ((flags & O_EXCL) && exists) {
- X /* Oops, the file exists and we didn't want it to. */
- X errno = EEXIST;
- X return -1;
- X }
- X /*
- X * If the file doesn't exist, be sure to call creat() so that
- X * it will be created with the proper mode.
- X */
- X if (!exists) call_creat = 1;
- X } else {
- X /* If O_CREAT isn't set and the file doesn't exist, error. */
- X if (!exists) {
- X errno = ENOENT;
- X return -1;
- X }
- X }
- X
- X /*
- X * If the O_TRUNC flag is set and the file exists, we want to call
- X * creat() anyway, since creat() guarantees that the file will be
- X * truncated and open()-for-writing doesn't.
- X * (If the file doesn't exist, we're calling creat() anyway and the
- X * file will be created with zero length.)
- X */
- X if ((flags & O_TRUNC) && exists) call_creat = 1;
- X /* actually do the call */
- X if (call_creat) {
- X /*
- X * call creat. May have to close and reopen the file if we
- X * want O_RDONLY or O_RDWR access -- creat() only gives
- X * O_WRONLY.
- X */
- X fd = creat(path,mode);
- X if (fd < 0 || (flags & O_WRONLY)) return fd;
- X if (close(fd) < 0) return -1;
- X /* Fall out to reopen the file we've created */
- X }
- X
- X /*
- X * calling old open, we strip most of the new flags just in case.
- X */
- X return open(path, flags & (O_RDONLY|O_WRONLY|O_RDWR|O_BINARY));
- X}
- X#endif
- X
- X#endif /* MASSCOMP mc700 */
- X#endif /* MASSCOMP mc500 */
- X#endif /* MASSCOMP mc300 */
- X
- X
- X
- X#if defined(MSDOS) || defined(AMIGA)
- X/* Fake mknod by complaining */
- Xint
- Xmknod(path, mode, dev)
- X char *path;
- X unsigned short mode;
- X dev_t dev;
- X{
- X extern int errno;
- X int fd;
- X
- X errno = ENXIO; /* No such device or address */
- X return -1; /* Just give an error */
- X}
- X
- X/* Fake links by copying */
- Xint
- Xlink(path1, path2)
- X char *path1;
- X char *path2;
- X{
- X char buf[256];
- X int ifd, ofd;
- X int nrbytes;
- X int nwbytes;
- X
- X fprintf(stderr, "%s: %s: cannot link to %s, copying instead\n",
- X tar, path1, path2);
- X if ((ifd = open(path1, O_RDONLY|O_BINARY)) < 0)
- X return -1;
- X if ((ofd = creat(path2, 0666)) < 0)
- X return -1;
- X#ifdef MSDOS
- X setmode(ofd, O_BINARY);
- X#endif
- X while ((nrbytes = read(ifd, buf, sizeof(buf))) > 0) {
- X if ((nwbytes = write(ofd, buf, nrbytes)) != nrbytes) {
- X nrbytes = -1;
- X break;
- X }
- X }
- X /* Note use of "|" rather than "||" below: we want to close
- X * the files even if an error occurs.
- X */
- X if ((nrbytes < 0) | (0 != close(ifd)) | (0 != close(ofd))) {
- X unlink(path2);
- X return -1;
- X }
- X return 0;
- X}
- X
- X/* everyone owns everything on MS-DOS (or is it no one owns anything?) */
- Xint
- Xchown(path, uid, gid)
- X char *path;
- X int uid;
- X int gid;
- X{
- X return 0;
- X}
- X
- Xint
- Xgeteuid()
- X{
- X return 0;
- X}
- X#endif /* MSDOS */
- END_OF_FILE
- if test 12968 -ne `wc -c <'port.c'`; then
- echo shar: \"'port.c'\" unpacked with wrong size!
- fi
- # end of 'port.c'
- fi
- echo shar: End of archive 3 \(of 5\).
- cp /dev/null ark3isdone
- MISSING=""
- for I in 1 2 3 4 5 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 5 archives.
- rm -f ark[1-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
- --
- Mail submissions (sources or binaries) to <amiga@cs.odu.edu>.
- Mail comments to the moderator at <amiga-request@cs.odu.edu>.
- Post requests for sources, and general discussion to comp.sys.amiga.
-